home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 3
/
Amiga Tools 3.iso
/
grafik
/
raytracing
/
rayshade-4.0.6.3
/
unapplied
/
multicsg
< prev
next >
Wrap
Text File
|
1994-08-09
|
15KB
|
578 lines
Multiple csg objects:
The patches to csg.c and csg.h make it possible to have more than
two objects in a CSG object. This is a little hack.
======================= cut here ========================
*** csg.h.orig Wed Jun 17 18:06:22 1992
--- csg.h Wed Jun 17 18:08:38 1992
***************
*** 34,40 ****
typedef struct Csg {
char operator; /* Union, Intersect, or Difference */
! struct Geom *obj1, *obj2;
int (*intmeth)(); /* Intersection method. */
Float bounds[2][3];
} Csg;
--- 34,41 ----
typedef struct Csg {
char operator; /* Union, Intersect, or Difference */
! struct Geom *list; /* Csg objects */
! int nobjs; /* Number of objects in the list */
int (*intmeth)(); /* Intersection method. */
Float bounds[2][3];
} Csg;
*** csg.c.orig Wed Jun 17 17:46:54 1992
--- csg.c Wed Jun 17 18:02:01 1992
***************
*** 40,46 ****
csg = (Csg *)share_malloc(sizeof(Csg));
csg->operator = op;
! csg->obj1 = csg->obj2 = (Geom *)NULL;
switch(op) {
--- 40,46 ----
csg = (Csg *)share_malloc(sizeof(Csg));
csg->operator = op;
! csg->list = (Geom *)NULL;
switch(op) {
***************
*** 82,123 ****
return csgName;
}
- csg_intersect_objs(csg, ray, hit1, hit2, mindist, dist1, dist2)
- Csg *csg;
- Ray *ray;
- HitList *hit1, *hit2;
- Float mindist, *dist1, *dist2;
- {
- int operator;
-
- hit1->nodes = 0;
- hit2->nodes = 0;
- *dist1 = FAR_AWAY;
- *dist2 = FAR_AWAY;
- operator = csg->operator;
-
- if (!intersect(csg->obj1, ray, hit1, mindist, dist1) &&
- ((operator == CSG_INTERSECT) || (operator == CSG_DIFFERENCE))) {
- /*
- * Intersection and Difference cases: if you miss the first
- * object, you missed the whole thing.
- */
- return FALSE;
- }
-
- if (!intersect(csg->obj2, ray, hit2, mindist, dist2) &&
- ((operator == CSG_INTERSECT) ||
- (hit1->nodes == 0) && (operator == CSG_UNION))) {
- /*
- * Intersect case: if you miss either object, you miss whole
- * Union case: if you miss both object, you miss whole
- */
- return FALSE;
- }
-
- return TRUE;
- }
-
int
csg_enter_obj(hitp)
HitList *hitp;
--- 82,87 ----
***************
*** 130,143 ****
}
static int
! CsgUnionInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
Ray *ray;
HitList *hit1p, *hit2p, **hitclose;
Float dist1, dist2, *distclose;
{
! Float distnext;
HitList hitnext, *hittmp;
while (TRUE) {
if (hit2p->nodes == 0 ||
csg_enter_obj(hit2p)) {
--- 94,120 ----
}
static int
! CsgUnionInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
! Csg *csg;
Ray *ray;
HitList *hit1p, *hit2p, **hitclose;
Float dist1, dist2, *distclose;
{
! Float disttmp, distnext;
HitList hitnext, *hittmp;
+ int sect, fl = 0;
+ if (dist1 > dist2) {
+ /* swap so 1 is closest */
+ disttmp = dist2;
+ dist2 = dist1;
+ dist1 = disttmp;
+ hittmp = hit1p;
+ hit1p = hit2p;
+ hit2p = hittmp;
+ fl = 1;
+ }
+
while (TRUE) {
if (hit2p->nodes == 0 ||
csg_enter_obj(hit2p)) {
***************
*** 149,156 ****
} else {
distnext = FAR_AWAY;
hitnext.nodes = 0;
! if (!intersect(hit1p->data[hit1p->nodes-1].obj,
! ray, &hitnext, dist2+EPSILON, &distnext)) {
/*
* None of obj1 beyond, return hit2 (leaving)
*/
--- 126,138 ----
} else {
distnext = FAR_AWAY;
hitnext.nodes = 0;
! if (fl || csg->nobjs == 1)
! sect = intersect(hit1p->data[hit1p->nodes-1].obj,
! ray, &hitnext, dist2+EPSILON, &distnext);
! else
! sect = CsgIntersect(csg,
! ray, &hitnext, dist2+EPSILON, &distnext);
! if (!sect) {
/*
* None of obj1 beyond, return hit2 (leaving)
*/
***************
*** 169,174 ****
--- 151,157 ----
dist1 = dist2;
CsgHitlistCopy(&hitnext, hit2p);
dist2 = distnext;
+ fl ^= 1;
/* and continue */
}
}
***************
*** 176,189 ****
}
static int
! CsgIntersectInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
Ray *ray;
HitList *hit1p, *hit2p, **hitclose;
Float dist1, dist2, *distclose;
{
HitList *hittmp, hitnext;
! Float distnext;
while (TRUE) {
if (!csg_enter_obj(hit2p)) {
/* Ray is leaving obj2 */
--- 159,185 ----
}
static int
! CsgIntersectInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
! Csg *csg;
Ray *ray;
HitList *hit1p, *hit2p, **hitclose;
Float dist1, dist2, *distclose;
{
HitList *hittmp, hitnext;
! Float disttmp, distnext;
! int sect, fl = 0;
+ if (dist1 > dist2) {
+ /* swap so 1 is closest */
+ disttmp = dist2;
+ dist2 = dist1;
+ dist1 = disttmp;
+ hittmp = hit1p;
+ hit1p = hit2p;
+ hit2p = hittmp;
+ fl = 1;
+ }
+
while (TRUE) {
if (!csg_enter_obj(hit2p)) {
/* Ray is leaving obj2 */
***************
*** 195,202 ****
} else {
distnext = FAR_AWAY;
hitnext.nodes = 0;
! if (!intersect(hit1p->data[hit1p->nodes-1].obj,
! ray, &hitnext, dist2+EPSILON, &distnext)) {
/*
* None of obj1 beyond, so return miss
*/
--- 191,203 ----
} else {
distnext = FAR_AWAY;
hitnext.nodes = 0;
! if (fl || csg->nobjs == 1)
! sect = intersect(hit1p->data[hit1p->nodes-1].obj,
! ray, &hitnext, dist2+EPSILON, &distnext);
! else
! sect = CsgIntersect(csg,
! ray, &hitnext, dist2+EPSILON, &distnext);
! if (!sect) {
/*
* None of obj1 beyond, so return miss
*/
***************
*** 213,218 ****
--- 214,220 ----
dist1 = dist2;
CsgHitlistCopy(&hitnext, hit2p);
dist2 = distnext;
+ fl ^= 1;
/* and continue */
}
}
***************
*** 220,226 ****
}
static int
! CsgDifferenceInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
Ray *ray;
HitList *hit1p, *hit2p, **hitclose;
Float dist1, dist2, *distclose;
--- 222,229 ----
}
static int
! CsgDifferenceInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
! Csg *csg;
Ray *ray;
HitList *hit1p, *hit2p, **hitclose;
Float dist1, dist2, *distclose;
***************
*** 227,232 ****
--- 230,236 ----
{
Float distnext;
HitList hitnext;
+ int sect;
while (TRUE) {
if (dist1 < dist2) {
***************
*** 240,247 ****
} else {
distnext = FAR_AWAY;
hitnext.nodes = 0;
! if (!intersect(hit1p->data[hit1p->nodes-1].obj,
! ray, &hitnext, dist2+EPSILON, &distnext)) {
/*
* None of obj1 beyond, so
* return miss
--- 244,256 ----
} else {
distnext = FAR_AWAY;
hitnext.nodes = 0;
! if (csg->nobjs == 1)
! sect = intersect(hit1p->data[hit1p->nodes-1].obj,
! ray, &hitnext, dist2+EPSILON, &distnext);
! else
! sect = CsgIntersect(csg,
! ray, &hitnext, dist2+EPSILON, &distnext);
! if (!sect) {
/*
* None of obj1 beyond, so
* return miss
***************
*** 298,341 ****
HitList *hitlist;
Float mindist, *maxdist;
{
! Float dist1, dist2, disttmp, distclose;
! HitList hit1, hit2, *hit1p, *hit2p, *hitclose;
! hit1p = &hit1;
! hit2p = &hit2;
! if (!csg_intersect_objs(csg, ray, hit1p, hit2p, mindist,
! &dist1, &dist2)) {
! /* missed the csg object */
return FALSE;
}
! if ((dist1 > dist2) &&
! (csg->operator == CSG_UNION || csg->operator == CSG_INTERSECT)) {
! /* swap so 1 is closest (except in difference case) */
! disttmp = dist2;
! dist2 = dist1;
! dist1 = disttmp;
! hit1p = &hit2;
! hit2p = &hit1;
! }
! /*
! * Call appropriate intersection method. If FALSE is return,
! * no hit of any kind was found.
! */
! if (!(*csg->intmeth)(ray, hit1p, hit2p, dist1, dist2,
! &hitclose, &distclose))
! return FALSE;
! /*
! * At this time, the closest hit is in hitclose and
! * distclose.
! */
! if (distclose < mindist || distclose > *maxdist)
return FALSE;
! CsgHitlistCopy(hitclose, hitlist);
! *maxdist = distclose;
return TRUE;
}
--- 307,384 ----
HitList *hitlist;
Float mindist, *maxdist;
{
! Float distcsg, distobj, distclose;
! HitList hit1, hit2, *hitclose, *hitcsgp, *hitobjp;
! int operator, nobjs;
! Geom *obj;
! operator = csg->operator;
!
! hitcsgp = &hit1;
! distcsg = FAR_AWAY;
! obj = csg->list;
! hitcsgp->nodes = 0;
! if (!intersect(obj, ray, hitcsgp, mindist, &distcsg) &&
! (operator == CSG_INTERSECT || operator == CSG_DIFFERENCE)) {
! /*
! * Intersection and Difference cases: if you miss the
! * first object, you missed the whole thing.
! */
return FALSE;
}
! hitobjp = &hit2;
! hitclose = &hit1;
! distclose = distcsg;
! nobjs = csg->nobjs;
! csg->nobjs = 0;
! while(++csg->nobjs < nobjs) {
! obj = obj->next;
! hitobjp->nodes = 0;
! distobj = FAR_AWAY;
! if (!intersect(obj, ray, hitobjp, mindist, &distobj)) {
! if (operator == CSG_INTERSECT) {
! csg->nobjs = nobjs;
! return FALSE;
! }
! if (hitcsgp->nodes == 0)
! continue;
! }
!
!
! /*
! * Call appropriate intersection method. If FALSE is return,
! * no hit of any kind was found.
! */
! if (!(*csg->intmeth)(csg, ray, hitcsgp, hitobjp, distcsg, distobj,
! &hitclose, &distclose) || distclose > *maxdist) {
! if (operator != CSG_UNION) {
! csg->nobjs = nobjs;
! return FALSE;
! }
! hitcsgp->nodes = 0;
! distcsg = FAR_AWAY;
! continue;
! }
!
! /*
! * At this time, the closest hit is in hitclose and
! * distclose.
! */
! distcsg = distclose;
! hitcsgp = hitclose;
! if (hitcsgp == &hit1)
! hitobjp = &hit2;
! else
! hitobjp = &hit1;
! }
! if (hitcsgp->nodes == 0 || distcsg < mindist || distcsg > *maxdist)
return FALSE;
! CsgHitlistCopy(hitcsgp, hitlist);
! *maxdist = distcsg;
return TRUE;
}
***************
*** 355,387 ****
Csg *csg;
Float bounds[2][3];
{
! GeomComputeBounds(csg->obj1);
! GeomComputeBounds(csg->obj2);
switch (csg->operator) {
case CSG_UNION:
! bounds[LOW][X] = min(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
! bounds[HIGH][X] = max(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
! bounds[LOW][Y] = min(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
! bounds[HIGH][Y] = max(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
! bounds[LOW][Z] = min(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
! bounds[HIGH][Z] = max(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
break;
case CSG_INTERSECT:
! bounds[LOW][X] = max(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
! bounds[HIGH][X] = min(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
! bounds[LOW][Y] = max(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
! bounds[HIGH][Y] = min(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
! bounds[LOW][Z] = max(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
! bounds[HIGH][Z] = min(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
break;
case CSG_DIFFERENCE:
- bounds[LOW][X] = csg->obj1->bounds[LOW][X];
- bounds[HIGH][X] = csg->obj1->bounds[HIGH][X];
- bounds[LOW][Y] = csg->obj1->bounds[LOW][Y];
- bounds[HIGH][Y] = csg->obj1->bounds[HIGH][Y];
- bounds[LOW][Z] = csg->obj1->bounds[LOW][Z];
- bounds[HIGH][Z] = csg->obj1->bounds[HIGH][Z];
break;
default:
RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
--- 398,438 ----
Csg *csg;
Float bounds[2][3];
{
! Geom *obj;
+ for (obj = csg->list; obj; obj = obj->next)
+ GeomComputeBounds(obj);
+
+ obj = csg->list;
+ bounds[LOW][X] = obj->bounds[LOW][X];
+ bounds[HIGH][X] = obj->bounds[HIGH][X];
+ bounds[LOW][Y] = obj->bounds[LOW][Y];
+ bounds[HIGH][Y] = obj->bounds[HIGH][Y];
+ bounds[LOW][Z] = obj->bounds[LOW][Z];
+ bounds[HIGH][Z] = obj->bounds[HIGH][Z];
+
switch (csg->operator) {
case CSG_UNION:
! while (obj = obj->next) {
! bounds[LOW][X] = min(bounds[LOW][X], obj->bounds[LOW][X]);
! bounds[HIGH][X] = max(bounds[HIGH][X], obj->bounds[HIGH][X]);
! bounds[LOW][Y] = min(bounds[LOW][Y], obj->bounds[LOW][Y]);
! bounds[HIGH][Y] = max(bounds[HIGH][Y], obj->bounds[HIGH][Y]);
! bounds[LOW][Z] = min(bounds[LOW][Z], obj->bounds[LOW][Z]);
! bounds[HIGH][Z] = max(bounds[HIGH][Z], obj->bounds[HIGH][Z]);
! }
break;
case CSG_INTERSECT:
! while (obj = obj->next) {
! bounds[LOW][X] = max(bounds[LOW][X], obj->bounds[LOW][X]);
! bounds[HIGH][X] = min(bounds[HIGH][X], obj->bounds[HIGH][X]);
! bounds[LOW][Y] = max(bounds[LOW][Y], obj->bounds[LOW][Y]);
! bounds[HIGH][Y] = min(bounds[HIGH][Y], obj->bounds[HIGH][Y]);
! bounds[LOW][Z] = max(bounds[LOW][Z], obj->bounds[LOW][Z]);
! bounds[HIGH][Z] = min(bounds[HIGH][Z], obj->bounds[HIGH][Z]);
! }
break;
case CSG_DIFFERENCE:
break;
default:
RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
***************
*** 424,454 ****
Geom *list;
{
static int OpenAdvised = FALSE;
! /*
! * Currently, this only handles two objects.
! * Will be fixed in the future.
! * No really we promise.
! */
! if (!list || !list->next) {
! RLerror(RL_WARN, "CSG needs at least two objects.\n");
return 0;
}
! if (list->next->next) {
! RLerror(RL_WARN, "Currently, CSG only handles two objects.\n");
! return 0;
}
/*
* Things are put into lists backwards....
*/
! csg->obj2 = list;
! csg->obj1 = list->next;
! if ((!csg->obj1->methods->closed || !csg->obj2->methods->closed) &&
! !OpenAdvised) {
! RLerror(RL_ADVISE,
! "Performing CSG with non-closed object(s).\n");
! OpenAdvised = TRUE;
}
! return csg->obj1->prims + csg->obj2->prims;
}
void
--- 475,517 ----
Geom *list;
{
static int OpenAdvised = FALSE;
! Geom *obj, *prev;
! int prims = 0;
! int nobjs = 0;
!
! if (!list) {
! RLerror(RL_WARN, "CSG needs at least one object.\n");
return 0;
}
! if (!list->next) {
! RLerror(RL_WARN, "CSG with only one object.\n");
}
+ prev = (Geom *)0;
+ for (obj = list; ; obj = obj->next) {
+ if ((!obj->methods->closed) &&
+ !OpenAdvised) {
+ RLerror(RL_ADVISE,
+ "Performing CSG with non-closed object(s).\n");
+ OpenAdvised = TRUE;
+ }
+ prims += obj->prims;
+ nobjs++;
+ if (!obj->next)
+ break;
+ prev = obj;
+ }
/*
* Things are put into lists backwards....
+ * To make the Difference methode work, we move the last
+ * element of the list to the head.
*/
! csg->list = obj;
! if (prev) {
! prev->next = 0;
! obj->next = list;
}
! csg->nobjs = nobjs;
! return prims;
}
void